use std::cell::RefCell;
use crate::class::vm_class::VMClassMethodDescriptor;

pub struct VMClassMethodDescriptorParser {
    offset: usize,
}


impl VMClassMethodDescriptorParser {
    pub fn new() -> VMClassMethodDescriptorParser {
        VMClassMethodDescriptorParser { offset: 0 }
    }

    pub fn parse(&mut self, desc: &String) -> VMClassMethodDescriptor {
        let mut arr = vec![];
        self.start();
        self.parse_param_type_list(&desc, &mut arr);
        self.end();
        let return_type = self.parse_result_type(&desc);
        return VMClassMethodDescriptor {
            class_method_descriptor_str: String::from(desc),
            param_type_list: RefCell::new(arr),
            return_type,
        };
    }


    fn start(&mut self) {
        self.offset = 1;
    }
    fn end(&mut self) {
        self.offset += 1;
    }

    fn parse_param_type_list(&mut self, desc: &String, arr: &mut Vec<String>) {
        loop {
            let result = self.parse_field_type(desc);
            if result.is_err() {
                break;
            }
            arr.push(result.unwrap())
        }
    }

    fn parse_result_type(&mut self, desc: &String) -> String {
        let temp_desc = desc[self.offset..].to_string();
        let start_ch = &temp_desc[0..1];
        if start_ch == "V" {
            self.offset = self.offset + 1;
            return "V".to_string();
        }
        return self.parse_field_type(desc).unwrap();
    }

    fn parse_field_type(&mut self, desc: &String) -> Result<String, String> {
        let temp_desc = desc[self.offset..].to_string();
        let start_ch = &temp_desc[0..1];
        self.offset = self.offset + 1;
        return match start_ch {
            "B" => { Ok(String::from("B")) }
            "C" => { Ok(String::from("C")) }
            "D" => { Ok(String::from("D")) }
            "F" => { Ok(String::from("F")) }
            "I" => { Ok(String::from("I")) }
            "J" => { Ok(String::from("J")) }
            "S" => { Ok(String::from("S")) }
            "Z" => { Ok(String::from("Z")) }
            "L" => {
                let end_index = temp_desc.find(";").unwrap();
                self.offset = self.offset + end_index;
                Ok(temp_desc[0..end_index].to_string())
            }
            "[" => {
                let result = self.parse_field_type(&desc);
                Ok(format!("[{}", result.unwrap()))
            }
            ")" => {
                self.offset = self.offset - 1;
                Err(String::from("参数列表解析结束"))
            }
            _ => { panic!("解析异常") }
        };
    }
}